#include "sysmonitor/cpu_tools.hpp"
#include "sysmonitor/utils.hpp"
#include <fstream>
#include <sstream>
#include <iostream>
#include <set>
#include <utility>
#include <algorithm>

namespace sysmonitor {
namespace cpu {

using namespace utils;
using namespace utils::string;

std::vector<CpuTime> getCpuTimes() {
    std::vector<CpuTime> cpuTimes;
    std::ifstream file("/proc/stat");
    if (!file.is_open()) {
        std::cerr << "Failed to open /proc/stat" << std::endl;
        return cpuTimes;
    }
  
    std::string line;
    while (std::getline(file, line) && line.rfind("cpu", 0) == 0) {
        std::istringstream ss(line);
        std::string cpuLabel;
        ss >> cpuLabel;

        uint64_t user = 0, nice = 0, system = 0, idle = 0, iowait = 0, irq = 0, softirq = 0, steal = 0;
        ss >> user >> nice >> system >> idle >> iowait >> irq >> softirq >> steal;

        CpuTime time;
        time.idle = idle + iowait;
        time.total = user + nice + system + idle + iowait + irq + softirq + steal;
        
        cpuTimes.push_back(time);
    }
  
    file.close();
    return cpuTimes;
}

CpuUsage calculateCpuUsage(const std::vector<CpuTime>& now, const std::vector<CpuTime>& prev) {
    CpuUsage usage;
    if (now.size() != prev.size() || now.empty()) {
        return usage;
    }
  
    for (size_t i = 0; i < now.size(); ++i) {
        const CpuTime& nowTime = now[i];
        const CpuTime& prevTime = prev[i];
      
        uint64_t totalDiff = nowTime.total > prevTime.total ? nowTime.total - prevTime.total : 0;
        
        if (totalDiff > 0) {
            uint64_t idleDiff = nowTime.idle > prevTime.idle ? nowTime.idle - prevTime.idle : 0;
            double coreUsage = static_cast<double>(totalDiff - idleDiff) / totalDiff * 100.0;
            coreUsage = std::max(0.0, std::min(100.0, coreUsage)); // 确保使用率在0-100之间

            if (i == 0) {
                usage.totalUsage = coreUsage;
            } else {
                usage.coreUsages.push_back(coreUsage);
            }
        } else {
            if (i == 0) {
                usage.totalUsage = 0.0;
            } else {
                usage.coreUsages.push_back(0.0);
            }
        }
    }
  
    return usage;
}


CpuInfo getCpuInfo() {
    CpuInfo info;
    std::ifstream file("/proc/cpuinfo");
    if (!file.is_open()) {
        std::cerr << "Failed to open /proc/cpuinfo" << std::endl;
        return info;
    }

    std::string line;
    int currentProcessor = -1;
    int currentPhysicalId = -1;
    int currentCoreId = -1;
    std::set<std::pair<int, int>> coreIds; // 用于计算物理核心数

    while (std::getline(file, line)) {
        size_t colonPos = line.find(':');
        if (colonPos == std::string::npos) continue;
      
        std::string key = trim(line.substr(0, colonPos));
        std::string value = trim(line.substr(colonPos + 1));

        if (key == "processor") {
            try {
                currentProcessor = std::stoi(value);
                info.threads = currentProcessor + 1; // 线程数等于 (最大processor索引 + 1)
            } catch(...) {}
        } else if (key == "model name" && info.modelName.empty()) {
            info.modelName = value;
        } else if (key == "cpu MHz") { // 获取最后一个cpu MHz值，通常更准
            try {
                info.mhz = std::stod(value);
            } catch (...) {}
        } else if (key == "cache size" && info.cacheSizeKB == 0) {
            try {
                info.cacheSizeKB = std::stoull(split(value, ' ')[0]);
            } catch (...) {}
        } else if (key == "physical id") {
            try {
                currentPhysicalId = std::stoi(value);
            } catch(...) {}
        } else if (key == "core id") {
            try {
                currentCoreId = std::stoi(value);
            } catch(...) {}
        }

        // 当一个processor块结束时（遇到空行或文件末尾），记录核心信息
        if (line.empty() || file.peek() == EOF) {
            if (currentPhysicalId != -1 && currentCoreId != -1) {
                coreIds.insert({currentPhysicalId, currentCoreId});
            }
            currentPhysicalId = -1;
            currentCoreId = -1;
        }
    }
    
    // 物理核心数等于唯一的(physical id, core id)对的数量
    info.cores = coreIds.size();
    
    // 如果无法通过core id计算，则回退到使用 "cpu cores" 字段
    if (info.cores == 0) {
        file.clear();
        file.seekg(0);
        while (std::getline(file, line)) {
            if (line.rfind("cpu cores", 0) == 0) {
                 try {
                    info.cores = std::stoi(trim(line.substr(line.find(':') + 1)));
                    break;
                } catch(...) {}
            }
        }
    }

    file.close();
    return info;
}

} // namespace cpu
} // namespace sysmonitor
